/*
 * _DoObject.h
 *
 *  Created on: Oct 18, 2012
 *      Author: wtao
 */

#ifndef DOOBJECT_H_
#define DOOBJECT_H_

#include "CxxUtils.h"

class DevilSemantic;
class DoNumber;
class DoBoolean;
class DoName;
class DoArray;
class DoString;
class DoProcedure;
class DoDictionary;
class DoFile;
using namespace std;

class _DoObject;

class onTokenListener
{
public:
	enum eContinueParse {
		eContinue,
		eStop,
		eLetMeSeeOneMore,
	};
	
public:
	virtual void onToken(CRefPtr< _DoObject > token) = 0;
	
	virtual eContinueParse onChar(int currChar) = 0;
};

class _DoObject
{
public:
	enum eObjType {
		eNull,
		eArray,
		ePackedArray,
		eBoolean,
		eComment,
		eDictionary,
		eName,
		eNumber,
		eProcedure,
		eString,
		eOperator,
		eFontId,
		eGraphicState,
		eFile,
		eMark,
	};	
protected:
	std::string mText;
	
	eObjType mObjType;
	
	int mLineNo;

	_DoObject(const _DoObject&);
	_DoObject& operator=(const _DoObject& obj);
	
	virtual void clone(_DoObject *dst, const _DoObject *src) {
		dst->mText = src->mText;
		dst->mObjType = src->mObjType;
		dst->mLineNo = src->mLineNo;
	}
	
	virtual CRefPtr< _DoObject > clone() {
		CXXTHROW;
	}

	static int nExecutionLevel;
public:
	_DoObject();
	virtual ~_DoObject();

	static CRefPtr< _DoObject > mNullObject;
	
	const char * getText() const {
		return mText.c_str();
	}

	void setText(const std::string &str) {
		mText = str;
	}

	int getLine() const {
		return mLineNo;
	}

	void setLine(int line) {
		mLineNo = line;
	}
	
	virtual eObjType type() const {
		return mObjType;
	}

	virtual bool executable() const {
		return false;
	}

	virtual void execute(DevilSemantic &semantic);

	virtual std::string _debug_dump() const{
		return mText;
	}
	
	virtual bool hashEqual(const CRefPtr< _DoObject > &obj) const;

	static CRefPtr< _DoObject > clone(CRefPtr< _DoObject > src);
	
	virtual bool equals(CRefPtr< _DoObject > obj) {
		return (this == obj.get());
	}
	
	static DoNumber * toNumber(CRefPtr< _DoObject > obj);
	
	static DoBoolean * toBoolean(CRefPtr< _DoObject > obj);
	
	static DoString * toString(CRefPtr< _DoObject > obj);
	
	static DoArray * toArray(CRefPtr< _DoObject > obj);
	
	static DoName * toName(CRefPtr< _DoObject > obj);
	
	static DoProcedure * toProc(CRefPtr< _DoObject > obj);
	
	static DoDictionary * toDict(CRefPtr< _DoObject > obj);
	
	static DoFile * toFile(CRefPtr< _DoObject > obj);
	
	static DoBoolean * toBool(CRefPtr< _DoObject > obj);
	
	static CRefPtr< _DoObject > newMark();
	
	static CRefPtr< _DoObject > newNumber(int i);
	
	static CRefPtr< _DoObject > newNumber(float f);
	
	static CRefPtr< _DoObject > newBool(bool b);
	
	static CRefPtr< _DoObject > newName(const char * str);
	
	static CRefPtr< _DoObject > newNull();
	
	static CRefPtr< _DoObject > newString(const std::string& str);
};

class _DoMark: public _DoObject
{
protected:
	_DoMark(const _DoMark&);
	_DoMark& operator=(const _DoMark&);
	
	virtual CRefPtr< _DoObject > clone() {
		_DoMark *p0 = new _DoMark();
		_DoObject::clone(p0, this);
		
		return CRefPtr< _DoObject >(p0);
	}
public:
	_DoMark() : _DoObject() {
		mObjType = _DoObject::eMark;
	}
	virtual ~_DoMark() {}
};

#endif /* DOOBJECT_H_ */
